#include "HeightMap.hpp"
#include "Graphics.hpp"
#include <Math/Random.hpp>
namespace zzz{
HeightMap::HeightMap()
{
  Left_ = -(MAP_SIZE / 2);
  Right_ = MAP_SIZE / 2;
  Front_ = MAP_SIZE / 2;
  Back_ = -(MAP_SIZE / 2);
  Generate();
}

HeightMap::~HeightMap()
{

}


float HeightMap::GetHeight(int x, int y)
{
  return HeightMap_[ToIndex(x,y)];
}

void HeightMap::SetHeight(int X, int Y, float h)
{
  HeightMap_[ToIndex(X,Y)]=h;
}

bool HeightMap::SetVertexColor(int x, int y)
{
  float fColor = float((GetHeight(x, y) / 256.0f) + 0.15);

  // Assign This Blue Shade To The Current Vertex
  glColor4f(fColor, fColor, fColor, 1.0f);

  return(true);
}

void HeightMap::GetVertexColor(int x, int y, float *col)
{
  if(!col) return;

  float fColor = float((GetHeight(x, y) / 256.0f) + 0.20);

  // Assign This Blue Shade To The Current Vertex
  col[0] = fColor;
  col[1] = fColor;
  col[2] = fColor;
  col[3] = 1.0f;
}

void HeightMap::DrawHeightMap(float drawsize)
{
  glBegin(GL_QUADS);
  for (float X = Left_; X < Right_; X++)
  {
    for (float Y = Back_; Y < Front_; Y++)
    {
      SetVertexColor(X,Y);
      glVertex3f(X/MAP_SIZE/2*drawsize,GetHeight(X,Y)/MAP_SIZE/2*drawsize,Y/MAP_SIZE/2*drawsize);
      SetVertexColor(X+1,Y);
      glVertex3f((X+1)/MAP_SIZE/2*drawsize,GetHeight(X+1,Y)/MAP_SIZE/2*drawsize,Y/MAP_SIZE/2*drawsize);
      SetVertexColor(X+1,Y+1);
      glVertex3f((X+1)/MAP_SIZE/2*drawsize,GetHeight(X+1,Y+1)/MAP_SIZE/2*drawsize,(Y+1)/MAP_SIZE/2*drawsize);
      SetVertexColor(X,Y+1);
      glVertex3f(X/MAP_SIZE/2*drawsize,GetHeight(X,Y+1)/MAP_SIZE/2*drawsize,(Y+1)/MAP_SIZE/2*drawsize);
    }
  }
  glEnd();
}

void HeightMap::Generate()
{
  RandSeed();
  HeightMap_[0]=0;
  for (int i=Back_+1; i<=Front_; i++)
    HeightMap_[ToIndex(Left_,i)]=HeightMap_[ToIndex(Left_,i-1)]+UniformRand(-0.5f,1.5f);
  for (int i=Left_+1; i<=Right_; i++)
  {
    HeightMap_[ToIndex(i,Back_)]=HeightMap_[ToIndex(i-1,Back_)]+UniformRand(-0.5f,1.5f);
    for (int j=Back_+1; j<=Front_; j++)
      HeightMap_[ToIndex(i,j)]=HeightMap_[ToIndex(i-1,j)]/2.0+HeightMap_[ToIndex(i,j-1)]/2.0+UniformRand(-0.5f,1.5f);
  }
}

int HeightMap::ToIndex(int x, int y) const
{
  x+=MAP_SIZE/2;
  y+=MAP_SIZE/2;
  if(x >= 0 && x <= MAP_SIZE && y >= 0 && y <= MAP_SIZE)
  {
    return x*(MAP_SIZE+1)+y;
  }
  return 0;
}
}